package com.kitty.game.activity.service.shidao;

import com.kitty.common.cache.RedisService;
import com.kitty.common.utils.SpringUtils;
import com.kitty.common.utils.ConcurrentHashSet;
import com.kitty.game.ServerService;
import com.kitty.game.activity.model.user.ShiDaoData;
import com.kitty.game.activity.model.user.ShiDaoMonsterData;
import com.kitty.game.activity.model.user.ShiDaoPKData;
import com.kitty.game.activity.service.time.FightActivityHandler;
import com.kitty.game.boss.config.BossSet;
import com.kitty.game.boss.model.BossFightParam;
import com.kitty.game.boss.model.BossParam;
import com.kitty.game.boss.service.NewBossService;
import com.kitty.game.config.NPC;
import com.kitty.game.enter.Position;
import com.kitty.game.equip.message.RespNotifyMiscEx;
import com.kitty.game.fight.bean.Fight;
import com.kitty.game.map.model.GroupMapParam;
import com.kitty.game.npc.model.NpcButton;
import com.kitty.game.role.model.Role;
import com.kitty.game.role.service.RoleService;
import com.kitty.game.team.model.Team;
import com.kitty.game.utils.Const;
import com.kitty.game.utils.TimeUtil;
import com.kitty.listener.event.FightEndEvent;
import com.kitty.mina.cache.DataCache;
import com.kitty.mina.message.MessagePusher;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;

import java.util.ArrayList;
import java.util.Calendar;
//import java.util.Iterator;
import java.util.List;
import java.util.Random;

/**试道大会挑战元魔阶段处理类*/
@Component
@Slf4j
public class ShiDaoMonsterHandler extends FightActivityHandler {
    @Autowired
    ShiDaoHandler shiDaoHandler;
    @Autowired
    RedisService redisService;
    private static final String YUANMO_NAME = "元魔";
    private static final int YUANMO_ICON = 6049;
    /**元魔持续时间，单位毫秒*/
    private static final long YUANMO_CONTINUED_TIME = 30 * TimeUtil.ONE_MINUTE;
    /**每个等级段试道开启的最少队伍数量*/
    private static final int MIN_TEAM_COUNT_SHIDAO_START = 15;
    /**最大回合数*/
    private static final byte MAX_ROUND = 20;
    private static final byte SCORE_KILL_YUANMO = 1;
    /**升到PK阶段的积分*/
    private static final int ENTER_PK_SCORE = 300;

    private static final String IN_FIGHT = "没看到我在忙吗？[离开]";

    private static final String WILL_START_MESSAGE = "#Y{0}#n级别的试道大会将于#R{1}分钟#n后在#R{2}#n开始报名，请有意参赛的玩家到该线#P试道申请人#P处报名参加。";
    private static final String START_SIGNUP_MESSAGE = "#Y{0}#n级别的试道大会在#R{1}#n开始报名啦，请有意参加的玩家赶快到该线#P试道申请人#P处报名参加哦！";
    private static final String START_MESSAGE = "#Y{0}#n级别的试道大会终于在#R{1}#n正式开始啦！究竟谁能笑傲试道场？让我们拭目以待吧！";
    private static final String SHIDAO_CANCEL_MESSAGE = "由于报名选手不足，#Y{0}#n级别的试道大会已被取消。";
    private static final String FIGHT_MONSTER_END_MESSAGE =  "中洲大陆果然能者辈出，#Y{0}#n级别的试道大会已经完成第一轮考验，现在高手之间可以进行较量了！";
    private static final String PK_WILL_MESSAGE = "#Y{0}#n级别的试道大会之#R巅峰对决#n即将开始，请大家做好准备！";


    private static final String CONTENT = "今天又可以活动活动筋骨了！真是开心呐！实力太弱的我可不陪他玩，如果#R{0}#n回合内没打败我，可是要被传出试道场外的！[让我试试你的厉害！/" + NpcButton.SHIDAO_DAHUI_FIGHT_YUANMO.getKey() + "][回头再说吧！/离开]";
    private static final String WIN_MESSAGE = "恭喜你取得了战斗胜利，获得了{0}点元魔积分，你当前的元魔积分为#R{1}#n点。";
    private static final String OUT_MESSAGE = "由于你挑战元魔的积分不足，无法参加试道大会的巅峰对决阶段。";


    public void checkSystemMessage(Calendar calendar) {
        ShiDaoData shiDaoData = shiDaoHandler.getShiDaoData();
        if (calendar.get(Calendar.MINUTE) == shiDaoData.getStartTime().get(Calendar.MINUTE) && calendar.get(Calendar.HOUR_OF_DAY) == shiDaoData.getStartTime().get(Calendar.HOUR_OF_DAY)-1) {
            shiDaoHandler.rangeHandle(levelRange -> {
                String serverName = SpringUtils.getBean(ServerService.class).getServer().getSonName();
                String msg = MessageFormat.format(WILL_START_MESSAGE, levelRange, 60, serverName);
                SpringUtils.getChatService().sendSystem(msg, Const.BRODCAST_MSG_TYPE_ROLE);
            });
        }

        if (calendar.get(Calendar.MINUTE) == shiDaoData.getSignupTime().get(Calendar.MINUTE) && calendar.get(Calendar.HOUR_OF_DAY) == shiDaoData.getSignupTime().get(Calendar.HOUR_OF_DAY)) {
            shiDaoHandler.rangeHandle(levelRange -> {
                String serverName = SpringUtils.getBean(ServerService.class).getServer().getSonName();
                String msg = MessageFormat.format(START_SIGNUP_MESSAGE, levelRange, serverName);
                SpringUtils.getChatService().sendSystem(msg, Const.BRODCAST_MSG_TYPE_ROLE);

                /**报名开始时就回收之前的王者称号*/
                shiDaoHandler.takeBackTitle(levelRange);
                shiDaoHandler.clearTopRecords(levelRange);
            });
        }
    }

    /**试道大会开始*/
    public void start() {
        log.info("试道大会开始");
        ShiDaoData shiDaoData = shiDaoHandler.getShiDaoData();
        /**挑战元魔阶段*/
        shiDaoData.setStage(ShiDaoData.STAGE_MONSTER);

        shiDaoHandler.rangeHandle(levelRange -> handleStart(levelRange));
    }

    private void handleStart(String levelRange) {
        List<Team> teamList = getLevelRangeTeams(levelRange);
        if (teamList.size() < shiDaoHandler.getShiDaoSet().getMinTeamCountShiDaoStart()) {
            handleTeamCountNotEnough(levelRange, teamList);
        } else {
            handleLevelRangeStart(levelRange, teamList);
        }
    }

    /**获得在试道场上对应等级段的队伍*/
    private List<Team> getLevelRangeTeams(String levelRange) {
        List<Team> teamList = new ArrayList<>();
        ConcurrentHashSet<Integer> roleIds = SpringUtils.getMapService().getRoleIds(new GroupMapParam(levelRange), Const.SHIDAO_MAPID);
        if (roleIds != null) {
            for (Integer roleId : roleIds) {
                Team team = SpringUtils.getTeamService().getTeam(roleId);
                if (team == null) {continue;}

                if (teamList.contains(team)) {continue;}
                teamList.add(team);
            }
        }
        return teamList;
    }

    /**在试道场上对应等级段的队伍数量不够时处理*/
    private void handleTeamCountNotEnough(String levelRange, List<Team> teamList) {
        /**记录已结束*/
        shiDaoHandler.getShiDaoData().getEndLevelRanges().add(levelRange);

        /**队伍数量少于开始的最小数量*/
        /**把对应等级段所有队伍移出试道场*/
        for (Team team : teamList) {
            Role leaderRole = SpringUtils.getRoleService().getOnlinePlayer(team.getLeaderUid());
            if (leaderRole == null) {continue;}
            shiDaoHandler.leaveShiDaoMap(leaderRole);
        }

        /**发送消息*/
        String msg = MessageFormat.format(SHIDAO_CANCEL_MESSAGE, levelRange);
        SpringUtils.getChatService().sendSystem(msg, Const.BRODCAST_MSG_TYPE_ROLE);
        log.info("{}, 队伍数量:{}", msg, (teamList!=null ? teamList.size() : 0));
    }

    private void handleLevelRangeStart(String levelRange, List<Team> teamList) {
        /**刷新元魔*/
        flushYuanMo(levelRange);
        /**更新为开始挑战元魔进度*/
        for (Team team : teamList) {
            teamService.memberHandle(team, memberRole -> shiDaoHandler.sendRespShidaoScore(memberRole));
        }
        initMonsterScores(levelRange, teamList);

        String serverName = SpringUtils.getBean(ServerService.class).getServer().getSonName();
        String msg = MessageFormat.format(START_MESSAGE, levelRange, serverName);
        SpringUtils.getChatService().sendSystem(msg, Const.BRODCAST_MSG_TYPE_ROLE);
        log.info("{}级别挑战元魔开始", levelRange);
    }

    /**初始化挑战元魔数据*/
    private void initMonsterScores(String levelRange, List<Team> teamList) {
        ShiDaoData shiDaoData = shiDaoHandler.getShiDaoData();
        for (Team team : teamList) {
            ShiDaoMonsterData shiDaoMonsterData = new ShiDaoMonsterData(team.getId());
            shiDaoData.getMonsterDataMap().put(team.getId(), shiDaoMonsterData);
            List<ShiDaoMonsterData> list = shiDaoData.getMonsterDataByLevel().computeIfAbsent(levelRange, k -> new ArrayList<>());
            list.add(shiDaoMonsterData);
        }
    }

    /**刷新元魔, 显示在对应的地图上*/
    private void flushYuanMo(String levelRange) {
        int yuanmoCount = Integer.parseInt(DataCache.REDIS_DATA.get("shidao_yuanmo_count_map"));
        for (int i = 0; i< yuanmoCount; i++) {
            createYuanMo(levelRange, Const.SHIDAO_MAPID);
        }
    }

    private void createYuanMo(String levelRange, int mapId) {
        Position position = getRandomPosition(mapId);
        NPC npc = new NPC();
        npc.setIcon(YUANMO_ICON);
        npc.setId(SpringUtils.getBean(NewBossService.class).getTempNpcId());
        npc.setX(position.getX());
        npc.setY(position.getY());
        npc.setFangxiang((short) new Random().nextInt(8));/**随机方向*/
        npc.setMapId(mapId);
        npc.setCreateTime(System.currentTimeMillis());
        npc.setEndTime(npc.getCreateTime() + YUANMO_CONTINUED_TIME);
        npc.setType(NPC.TYPE_YUANMO);
        String content = MessageFormat.format(CONTENT, MAX_ROUND);
        npc.setContent(content);
        npc.setName(YUANMO_NAME);
        npc.setBossSetName(YUANMO_NAME);
        GroupMapParam groupMapParam = new GroupMapParam(levelRange);

        SpringUtils.getMapService().addGroupMapNpc(groupMapParam, npc);
        bossService.broadcastNpcShow(groupMapParam, npc);
    }

    /**删除元魔*/
    private void removeYuanMo(String levelRange, NPC bossNpc) {
        GroupMapParam groupMapParam = new GroupMapParam(levelRange);
        SpringUtils.getMapService().removeGroupMapNpc(groupMapParam, bossNpc);
        bossService.broadcastNpcHide(groupMapParam, bossNpc);
    }

    /**挑战阶段结束*/
    public void end() {
        shiDaoHandler.rangeHandle(levelRange -> handleEnd(levelRange));
    }

    private void handleEnd(String levelRange) {
        ShiDaoData shiDaoData = shiDaoHandler.getShiDaoData();
        /**已经结束时，则不处理后面逻辑(可能因为队伍人数不足未开始)*/
        if (shiDaoData.getEndLevelRanges().contains(levelRange)) {return ;}

        clearAllYuanMo(levelRange);
        quitAllFight(levelRange);

        log.error("挑战元魔结束后开始初始化pk数据=={}",levelRange);
        /**统计元魔积分*/
        List<ShiDaoMonsterData> listByRange = shiDaoData.getMonsterDataByLevel().get(levelRange);
        if (listByRange != null) {
            for (ShiDaoMonsterData shiDaoMonsterData : listByRange) {
                Team team = teamService.getTeamByTeamId(shiDaoMonsterData.getTeamId());
                if (team == null) {continue; }

                int totalMonsterScore = shiDaoMonsterData.getMonsterScore() * teamService.getTeamCount(team);
//                if (totalMonsterScore >= shiDaoHandler.getShiDaoSet().getMinMonsterScorePK()) {
                /**加入PK阶段列表*/
//                    short pkValue = (short) (totalMonsterScore / 20 + 1);
                /**PK值小于3时，等于3*/
//                    if (pkValue < 3) {pkValue = 3;}
                short pkValue = 5;
                ShiDaoPKData shiDaoPKData = new ShiDaoPKData(team, pkValue);
                shiDaoData.getPkDataMap().put(team.getId(), shiDaoPKData);
                List<ShiDaoPKData> list = shiDaoData.getPkDataByLevel().computeIfAbsent(levelRange, k -> new ArrayList<>());
                list.add(shiDaoPKData);

                log.info("{}进入试道巅峰对决,积分:{}", team.getName(), totalMonsterScore);
//                }
//                else {
//                    /**移出试道场*/
//                    Role leaderRole = SpringUtils.getRoleService().getOnlinePlayer(team.getLeaderUid());
//                    shiDaoHandler.leaveShiDaoMap(leaderRole);
//
//                    teamService.pushMessageToTeam(team, new RespNotifyMiscEx(OUT_MESSAGE));
//
//                    logger.info("{}试道元魔积分不足，移出试道场,积分:{}", team.getName(), totalMonsterScore);
//                }
            }
        }


        String msg = MessageFormat.format(FIGHT_MONSTER_END_MESSAGE, levelRange);
        SpringUtils.getChatService().sendSystem(msg, Const.BRODCAST_MSG_TYPE_ROLE);

        msg = MessageFormat.format(PK_WILL_MESSAGE, levelRange);
        SpringUtils.getChatService().sendSystem(msg, Const.BRODCAST_MSG_TYPE_ROLE);
    }



    /**删除所有元魔*/
    private void clearAllYuanMo(String levelRange) {
        GroupMapParam groupMapParam = new GroupMapParam(levelRange);
        List<NPC> npcList = SpringUtils.getMapService().getNpcList(groupMapParam, Const.SHIDAO_MAPID);
        if (npcList == null) {return ;}

        for (NPC npc : npcList) {
            if (npc.getType() != NPC.TYPE_YUANMO) {continue;}

            SpringUtils.getMapService().removeGroupMapNpc(groupMapParam, npc);
            SpringUtils.getBean(NewBossService.class).broadcastNpcHide(groupMapParam, npc);
        }
    }

    /**结束所有挑战元魔战斗*/
    private void quitAllFight(String levelRange) {
        GroupMapParam groupMapParam = new GroupMapParam(levelRange);
        Set<Integer> roleIds = SpringUtils.getMapService().getRoleIds(groupMapParam, Const.SHIDAO_MAPID);
        if (roleIds != null) {
            for (int roleId : roleIds) {
                Role role = SpringUtils.getRoleService().getOnlinePlayer(roleId);
                if (role == null) {continue;}
                if (teamService.isTeamLeader(role)) {
                    Fight fight = SpringUtils.getFightService().getFightByRoleId(role.getRoleId());
                    if (fight != null) {
                        SpringUtils.getFightService().quitFight(fight);
                    }
                }
            }
        }
    }

    @Override
    protected String getNpcContent(Role role, NPC bossNpc) {
        return null;
    }

    @Override
    protected String getNpcContentNotFight(Role role, NPC bossNpc) {
        /**检测是否在战斗中*/
        if (bossNpc.isInFight()) {
            return IN_FIGHT;
        }

        return null;
    }

    @Override
    protected void doStartFight(Role role, NPC bossNpc) {
        List<BossParam> bossParamList = newBossParamList(role, bossNpc);
        BossFightParam bossFightParam = new BossFightParam(bossParamList, getFightType(role));
        bossFightParam.setNpcId(bossNpc.getId());
        Fight fight = bossService.startFightToBoss(role, bossFightParam);
        fight.setMaxRound(MAX_ROUND);
    }

    private List<BossParam> newBossParamList(Role role, NPC bossNpc) {
        List<BossParam> bossParamList = new ArrayList<>();
        int count = getBossCount(role);

        /**npc对应的加在第1个*/
        BossSet bossSet = bossService.getBossSet(bossNpc.getBossSetName());
        bossParamList.add(new BossParam(bossSet, bossNpc.getName()));

        /**加count-1个*/
        for (int i=1; i<count; i++) {
            bossSet = bossService.getBossSet(bossNpc.getBossSetName());
            bossParamList.add(new BossParam(bossSet, bossSet.getName()));
        }

        return bossParamList;
    }

    public int getBossCount(Role role) {
        /**最多有10个*/
        int allCount = 10;
        int teamCount = teamService.getTeamCount(role);

        /**根据组队数量计算怪的数量*/
        int count = 0;
        if (teamCount <= 3) {
            int minCount = 6;
            count = ThreadLocalRandom.current().nextInt(allCount - minCount + 1)  + minCount;
        } else if (teamCount == 4){
            int minCount = 8;
            count = ThreadLocalRandom.current().nextInt(allCount - minCount + 1)  + (minCount);
        } else {
            count = allCount;
        }
        return count;
    }

    @Override
    protected int getFightType(Role role) {
        ShiDaoData shiDaoData = shiDaoHandler.getShiDaoData();
        if (shiDaoData != null&&shiDaoData.isMonthTao()) {
            return Const.fightType_month_shidao_yuanmo;
        }
        return Const.fightType_shidao_yuanmo;
    }

    @Override
    protected NPC getBossNpc(int npcId) {
        return SpringUtils.getMapService().getNpc(npcId);
    }

    @Override
    protected void clearNpcAfterWin(Role role, NPC bossNpc) {
        String levelRange = shiDaoHandler.getLevelRange(role);
        removeYuanMo(levelRange, bossNpc);

        /**挑战元魔阶段没结束时，需要每被杀死一个再刷新一个出来*/
        ShiDaoData shiDaoData = shiDaoHandler.getShiDaoData();
        if (Calendar.getInstance().before(shiDaoData.getMonsterEndTime())) {
            createYuanMo(levelRange, Const.SHIDAO_MAPID);
        }
    }

    @Override
    protected void giveReward(Role role, FightEndEvent fightEndEvent, NPC bossNpc) {
        /**增加元魔积分*/
        if (teamService.isTeamLeader(role)) {
            Team team = teamService.getTeam(role.getRoleId());
            ShiDaoData shiDaoData = shiDaoHandler.getShiDaoData();
            ShiDaoMonsterData shiDaoMonsterData = shiDaoData.getMonsterDataMap().get(team.getId());
            if (shiDaoMonsterData != null) {
                /**队伍增加元魔积分*/
                shiDaoMonsterData.addMonsterScore(shiDaoHandler.getShiDaoSet().getScoreKillMonster());
                /**提示信息*/
                int teamCount = teamService.getTeamCount(team);
                String msg = MessageFormat.format(WIN_MESSAGE, shiDaoHandler.getShiDaoSet().getScoreKillMonster()*teamCount, shiDaoMonsterData.getMonsterScore()*teamCount);
                MessagePusher.pushMessage(role, new RespNotifyMiscEx(msg));

                /**主动更新积分显示*/
                teamService.memberHandle(team, memberRole -> shiDaoHandler.sendRespShidaoScore(memberRole));

                log.info("{}增加元魔积分:{}", team.getMemberNames(), shiDaoHandler.getShiDaoSet().getScoreKillMonster());
            }
        }

        /**给其他奖励试道元魔给阴德和洛书经验*/
        SpringUtils.getBossService().giveRewardShidao(role, fightEndEvent, 1, bossNpc.getLevel());
        RoleService roleService = SpringUtils.getRoleService();
        { roleService.addluoshuExp(role, 200);}
        { roleService.addYinde(role, 10, true); }
    }

    @Override
    protected void clearNpcTimeOut(NPC npc) {

    }

    @Override
    public void doFightFail(Role role, FightEndEvent fightEndEvent) {
        super.doFightFail(role, fightEndEvent);

//        shiDaoHandler.leaveShiDaoMap(role);
    }

    @Override
    public void doFightRunAway(Role role, FightEndEvent fightEndEvent) {
        super.doFightRunAway(role, fightEndEvent);

        shiDaoHandler.leaveShiDaoMap(role);
    }

    @Override
    public void doFightMaxRound(Role role, FightEndEvent fightEndEvent) {
        super.doFightMaxRound(role, fightEndEvent);

        shiDaoHandler.leaveShiDaoMap(role);
    }
}
